/*-*-C-*-
 *
 * Item resizing code
 */

#include "resed.h"

/*
 * Resize a simple icon so that its highlight bounding box exactly corresponds
 * with bbox.  The bbox passed in is work-area relative.  Remember to
 * redraw the item afterwards.
 */

static error * resize_simple (ResourcePtr res, ItemInfoPtr item, RectPtr bbox)
{
    RectRec oldbbox;

    /* Invalidate the old bbox */

    template_item_bbox (res, item, &oldbbox);
    template_adjust_item_bbox (AddHighlight, &oldbbox, &oldbbox);
    wimp_invalidate (&res->window, &oldbbox);

    /* Set the single icon to the new bbox size */

    res->icons[item->u.master].icon.bbox = *bbox;
    
    /* Invalidate the new bbox */

    template_adjust_item_bbox (AddHighlight, bbox, bbox);
    wimp_invalidate (&res->window, bbox);
    return NULL;
}


/*
 * Resize a group item such that the label stays at the same offset from
 * the top left of the main icon.  Also make sure that the label is exactly
 * the right size for the text contained.
 */

static error * resize_group (ResourcePtr res, ItemInfoPtr item, RectPtr bbox)
{
    GroupBoxPtr group = &item->u.groupbox;
    RectPtr labelbbox = &res->icons[group->label].icon.bbox;
    RectPtr boxbbox = &res->icons[group->box].icon.bbox;
    RectRec oldbbox;
    int w, h, offset = labelbbox->minx - boxbbox->minx;

    /* Invalidate the old bbox */

    template_item_bbox (res, item, &oldbbox);
    template_adjust_item_bbox (AddHighlight, &oldbbox, &oldbbox);
    wimp_invalidate (&res->window, &oldbbox);

    /* Recalculate proper label bbox */

    template_icon_size (&res->icons[group->label].icon, &w, &h);
    w += scalex * 4;            /* Some extra pixels */
    h += scaley * 4;

    labelbbox->maxy = bbox->maxy;
    labelbbox->miny = bbox->maxy - h;
    labelbbox->minx = bbox->minx + offset;
    labelbbox->maxx = labelbbox->minx + w;

    /* Don't let the whole bbox get smaller than the label */

    wimp_merge_bboxes (bbox, bbox, labelbbox);
    
    /* Calculate the proper frame bbox */

    *boxbbox = *bbox;
    boxbbox->maxy -= h / 2;

    /* Invalidate the new bbox */

    template_adjust_item_bbox (AddHighlight, bbox, bbox);
    wimp_invalidate (&res->window, bbox);
    return NULL;
}
    

/*
 * Resize a hslider item.  The channel becomes the new size.  The gaps between the channel and
 * the two "stripe" icons should remain fixed (at its current value).
 * The height and width of the two stripe icons should increase or decrease
 * as appropriate (but keep the values sensible, increasing the new bbox if necessary).
 */

#define MINWIDTH 32
#define MINHEIGHT 16

static error * resize_hslider (ResourcePtr res, ItemInfoPtr item, RectPtr bbox)
{
    SliderPtr hslider = &item->u.slider;
    RectPtr wellbbox = &res->icons[hslider->well].icon.bbox;
    RectPtr trackbbox = &res->icons[hslider->track].icon.bbox;
    RectPtr knobbbox = &res->icons[hslider->knob].icon.bbox;
    int leftgap = trackbbox->minx - wellbbox->minx;
    int rightgap = wellbbox->maxx - trackbbox->maxx;
    int botgap = trackbbox->miny - wellbbox->miny;
    int topgap = wellbbox->maxy - trackbbox->maxy;
    int delta;

    RectRec oldbbox;

    /* Invalidate the old bbox */

    template_item_bbox (res, item, &oldbbox);
    template_adjust_item_bbox (AddHighlight, &oldbbox, &oldbbox);
    wimp_invalidate (&res->window, &oldbbox);

    /* If the new bbox is too small, then extend at bottom right */
    delta = (bbox->maxx - bbox->minx) - leftgap - rightgap;
    if (delta < MINWIDTH)
        bbox->maxx += MINWIDTH - delta;

    delta = (bbox->maxy - bbox->miny) - botgap - topgap;
    if (delta < MINHEIGHT)
        bbox->miny -= MINHEIGHT - delta;

    /* Set the bbox of the well to be the new bbox */
    *wellbbox = *bbox;
    
    /* Set the bbox of the track */
    trackbbox->minx = bbox->minx + leftgap;
    trackbbox->maxx = bbox->maxx - rightgap;
    trackbbox->miny = bbox->miny + botgap;
    trackbbox->maxy = bbox->maxy - topgap;

    /* Set the bbox of the knob.  The width used is just half that
     * of the track
     */

    *knobbbox = *trackbbox;
    knobbbox->maxx = knobbbox->minx + (trackbbox->maxx - trackbbox->minx) / 2;
    
    /* Invalidate the new bbox */

    template_adjust_item_bbox (AddHighlight, bbox, bbox);
    wimp_invalidate (&res->window, bbox);
    return NULL;
}

#undef MINWIDTH
#undef MINHEIGHT
    

/*
 * Resize a vslider item.  The channel becomes the new size.  The gaps between the channel and
 * the two "stripe" icons should remain fixed (at its current value).
 * The height and width of the two stripe icons should increase or decrease
 * as appropriate (but keep the values sensible, increasing the new bbox if necessary).
 */

#define MINWIDTH 16
#define MINHEIGHT 32

static error * resize_vslider (ResourcePtr res, ItemInfoPtr item, RectPtr bbox)
{
    SliderPtr vslider = &item->u.slider;
    RectPtr wellbbox = &res->icons[vslider->well].icon.bbox;
    RectPtr trackbbox = &res->icons[vslider->track].icon.bbox;
    RectPtr knobbbox = &res->icons[vslider->knob].icon.bbox;
    int leftgap = trackbbox->minx - wellbbox->minx;
    int rightgap = wellbbox->maxx - trackbbox->maxx;
    int botgap = trackbbox->miny - wellbbox->miny;
    int topgap = wellbbox->maxy - trackbbox->maxy;
    int delta;

    RectRec oldbbox;

    /* Invalidate the old bbox */

    template_item_bbox (res, item, &oldbbox);
    template_adjust_item_bbox (AddHighlight, &oldbbox, &oldbbox);
    wimp_invalidate (&res->window, &oldbbox);

    /* If the new bbox is too small, then extend at bottom right */
    delta = (bbox->maxx - bbox->minx) - leftgap - rightgap;
    if (delta < MINWIDTH)
        bbox->maxx += MINWIDTH - delta;

    delta = (bbox->maxy - bbox->miny) - botgap - topgap;
    if (delta < MINHEIGHT)
        bbox->miny -= MINHEIGHT - delta;

    /* Set the bbox of the well to be the new bbox */
    *wellbbox = *bbox;
    
    /* Set the bbox of the track */
    trackbbox->minx = bbox->minx + leftgap;
    trackbbox->maxx = bbox->maxx - rightgap;
    trackbbox->miny = bbox->miny + botgap;
    trackbbox->maxy = bbox->maxy - topgap;

    /* Set the bbox of the knob.  The height used is just half that
     * of the track
     */

    *knobbbox = *trackbbox;
    knobbbox->maxy = knobbbox->miny + (trackbbox->maxy - trackbbox->miny) / 2;
    
    /* Invalidate the new bbox */

    template_adjust_item_bbox (AddHighlight, bbox, bbox);
    wimp_invalidate (&res->window, bbox);
    return NULL;
}
    

/*
 * Deny resize operation
 */

static error * resize_deny (ResourcePtr res, ItemInfoPtr item, RectPtr bbox)
{
    return NULL;
}


/*
 * Table of resize procedures for each type of item
 */

static ResizeProc resizeproc[] =
{
    resize_simple,              /* Simple icon */
    resize_simple,              /* Command */
    resize_simple,              /* Label */
    resize_simple,              /* Display field */
    resize_simple,              /* Writeable field */
    resize_hslider,             /* HSlider */
    resize_vslider,             /* VSlider */
    resize_simple,              /* Option button */
    resize_simple,              /* Radio button */
    resize_group,               /* Group box */
    resize_deny,                /* Menu button */
    resize_deny,                /* Adjuster button */
};


error * resize_item (ResourcePtr res, ItemInfoPtr item, RectPtr rect)
{
    return (resizeproc[item->type]) (res, item, rect);
}
